using AppToolKit.Business.Observer;
using AppToolKit.Core.Context.Spring.AutoConstruction;
using AppToolKit.Core.Context.Spring.Register;
using AppToolKit.Core.Logging;
using Common.Logging;
using Spring.Context;
using Spring.Context.Support;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
namespace AppToolKit.Core.Context.Spring
{
	public class ContextManager : IApplicationContextAware, IObjectPostProcessor, IContextManager
	{
		private Dictionary<string, string> cache_ = new Dictionary<string, string>();
		private ContextRegisterManager register_;
		private static readonly ILog logger_ = LogManager.GetLogger(DefaultLogger.LOGGER_NAME);
		private ContextHelper helper_;
		private IApplicationContext context_;
		public List<IBusinessBuilder> Builderes
		{
			get;
			set;
		}
		public IScopeImplManager ScopeManager
		{
			private get;
			set;
		}
		public IApplicationContext ApplicationContext
		{
			get
			{
				return this.context_;
			}
			set
			{
				Debug.Assert(value != null);
				this.context_ = value;
				this.helper_ = new ContextHelper(value);
				this.register_ = new ContextRegisterManager(value);
			}
		}
		public void AutowireObject(object target)
		{
			this.DoAutowireObject(target);
			if (target is ISubject)
			{
				ISubject subject = (ISubject)target;
				if (subject.ObserveMgr == null)
				{
					subject.ObserveMgr = (IObserverManager)this.helper_.GetObject(typeof(IObserverManager));
				}
				ContextManager.logger_.Debug(string.Format("assign observemgr{0}", target.GetType()));
			}
			if (target is ILoggingable)
			{
				ILoggingable loggingable = (ILoggingable)target;
				loggingable.LoggerFixture = (ILoggerFixture)this.helper_.GetObject(typeof(ILoggerFixture));
				ContextManager.logger_.Debug(string.Format("assign logger{0}", target.GetType()));
			}
			if (target is IAutoWiringAfterProcess)
			{
				((IAutoWiringAfterProcess)target).PostProcessAfterWiring(this);
			}
		}
		public void Dispose<T>()
		{
			this.Dispose(typeof(T));
		}
		public void Dispose(Type t)
		{
			string objectName = this.helper_.GetObjectName(t);
			this.Dispose(objectName);
		}
		public void Dispose(string objectName)
		{
			ContextManager.logger_.Debug(string.Format("fatctory name is {0}", objectName));
			DefaultListableObjectFactory defaultListableObjectFactory = (DefaultListableObjectFactory)((XmlApplicationContext)this.context_).ObjectFactory;
			if (defaultListableObjectFactory.GetObjectDefinition(objectName).IsSingleton)
			{
				defaultListableObjectFactory.Dispose();
			}
		}
		private void DoAutowireObject(object target)
		{
			ContextManager.logger_.Debug(string.Format("装配新对象{0},{1:yyyy-MM-dd HH:mm:ss.fff}", target.GetType().Name, DateTime.Now));
			Type type = target.GetType();
			PropertyInfo[] properties = type.GetProperties();
			for (int i = 0; i < properties.Length; i++)
			{
				PropertyInfo propertyInfo = properties[i];
				if (propertyInfo.IsDefined(typeof(AutoWiringAttribute), false))
				{
					try
					{
						AutoWiringAttribute autoWiringAttribute = (AutoWiringAttribute)propertyInfo.GetCustomAttributes(typeof(AutoWiringAttribute), false)[0];
						object value;
						if (autoWiringAttribute.Scope == ContextScope.Assembly)
						{
							value = this.DoGetObjectByAssembly(type.Assembly.FullName, propertyInfo.PropertyType);
						}
						else
						{
							if (autoWiringAttribute.Method == WiringMethod.ByName)
							{
								value = this.context_.GetObject(autoWiringAttribute.Name);
							}
							else
							{
								value = this.GetAutoWiringObject(propertyInfo.PropertyType);
							}
						}
						propertyInfo.SetValue(target, value, null);
					}
					catch (Exception ex)
					{
						ContextManager.logger_.Error(string.Format("装配对象{0}失败,装配服务报错({1})", target.GetType().Name, ex.GetBaseException().Message));
						ContextManager.logger_.Error(ex.GetBaseException().StackTrace);
						throw;
					}
				}
			}
			ContextManager.logger_.Debug(string.Format("装配新对象{0}完毕,{1:yyyy-MM-dd HH:mm:ss.fff}", target.GetType().Name, DateTime.Now));
		}
		private object DoGetObjectByAssembly(string scope, Type type)
		{
			object result = null;
			if (this.ScopeManager == null)
			{
				throw new ContextManageException("Scope Manager为null,无法按模块来wiring");
			}
			Type unqiureTypeByScope = this.ScopeManager.GetUnqiureTypeByScope(scope, type);
			if (unqiureTypeByScope != null)
			{
				result = this.GetAutoWiringObject(unqiureTypeByScope);
			}
			return result;
		}
		public T Create<T>()
		{
			T t = Activator.CreateInstance<T>();
			this.AutowireObject(t);
			return t;
		}
		public T Create<T>(params object[] args)
		{
			object obj = Activator.CreateInstance(typeof(T), args);
			this.AutowireObject(obj);
			return (T)obj;
		}
		public object Create(Type type)
		{
			object obj = Activator.CreateInstance(type);
			this.AutowireObject(obj);
			return obj;
		}
		public object Create(Type type, params object[] args)
		{
			object obj = Activator.CreateInstance(type, args);
			this.AutowireObject(obj);
			return obj;
		}
		public bool ContainsObject(Type type)
		{
			return this.helper_.ContainsObject(type);
		}
		public object GetObject(string name)
		{
			return this.helper_.GetObject(name);
		}
		public object GetObject(Type type)
		{
			return this.GetAutoWiringObject(type);
		}
		public object GetObjectByAssembly(string assembly, Type type)
		{
			return this.DoGetObjectByAssembly(assembly, type);
		}
		public T GetObject<T>()
		{
			return (T)this.helper_.GetObject(typeof(T));
		}
		public void Register(Type type, bool singleton)
		{
			this.register_.Register(type, singleton);
		}
		private object GetAutoWiringObject(Type type)
		{
			object obj = null;
			if (this.cache_.ContainsKey(type.FullName))
			{
				obj = this.helper_.GetObject(this.cache_[type.FullName]);
				ContextManager.logger_.Debug(string.Format("cache hit:{0}", type.FullName));
			}
			else
			{
				Debug.Assert(this.helper_ != null);
				if (this.helper_.ContainsObject(type))
				{
					this.cache_[type.FullName] = this.helper_.GetObjectName(type);
					obj = this.helper_.GetObject(this.cache_[type.FullName]);
				}
				else
				{
					foreach (IBusinessBuilder current in this.Builderes)
					{
						if (current.IsSupport(type))
						{
							obj = current.GetObject(type);
						}
					}
				}
				if (obj == null)
				{
					throw new ContextManageException(string.Format("{0}找不到可用的服务", type.FullName));
				}
			}
			return obj;
		}
		public string GetObjectName(Type type)
		{
			return this.helper_.GetObjectName(type);
		}
		public object PostProcessBeforeInitialization(object instance, string name)
		{
			XmlApplicationContext xmlApplicationContext = this.context_ as XmlApplicationContext;
			if (instance.GetType().IsDefined(typeof(AutoWiringAttribute), false) || instance is IAutoWiring)
			{
				this.AutowireObject(instance);
			}
			return instance;
		}
		public object PostProcessAfterInitialization(object instance, string objectName)
		{
			return instance;
		}
		public bool IsSingleton(Type type)
		{
			string objectName = this.GetObjectName(type);
			return this.context_.IsSingleton(objectName);
		}
	}
}
